package exam2006.question12;

import java.lang.reflect.Field;
import java.util.ArrayList;

public class ex1 {

	public ex1() {
	}

	public Class doNotHaveSuper(Class[] classes) {

		int i;
		for (i = 0; i < classes.length; i++)
			if (classes[i].getSuperclass().getName().equals("java.lang.Object")) {

				Class res = classes[i];
				classes[i] = null;

				return res;
			}

		return null;
	}

	public int findInd(Class c, ArrayList<Class> list) {

		int ind = 0;

		if (list.isEmpty())
			return ind;

		ind = 0;

		Class pred = list.get(0);
		for (Class current : list) {

			if (c.isAssignableFrom(current))
				if (pred.isAssignableFrom(c) || pred == current)
					return ind;
			if (pred!=current && c.getSuperclass().getName().equals(pred.getName()))
				return ind;

			ind++;
			pred = current;

		}
		ind = list.size();
		return ind;
	}

	public ArrayList<Class> trieClasses(Class[] classes) {
		ArrayList<Class> res = new ArrayList<Class>();

		int ind;

		for (Class c : classes) {
			ind = findInd(c, res);
			res.add(ind, c);
		}

		return res;

	}

	public boolean sameFieldAndType(Field[] fields, String[] noms,
			Object[] valeurs) {

		if (fields.length != noms.length)
			return false;

		for (int i = 0; i < fields.length; i++) {
			String left = fields[i].getName();
			String right = noms[i];
			Class leftC = fields[i].getType();
			Class rightC = valeurs[i].getClass();
			if (!(left.equals(right) && leftC.isAssignableFrom(rightC)))
				return false;
		}

		return true;
	}

	public Field[] getAllField(Class c) {

		Field[] result = null;

		Class superClass = c.getSuperclass();

		Field[] current = c.getDeclaredFields();

		if (c.getSuperclass() != null) {
			Field[] others = getAllField(c.getSuperclass());

			result = new Field[current.length + others.length];

			int i;
			for (i = 0; i < others.length; i++)
				result[i] = others[i];

			for (int j = 0; j < current.length; j++) {
				result[i++] = current[j];
			}

		} else {
			result = current;
		}

		return result;
	}

	// question 2
	public Object classifieEtCreerDe(String[] noms, Object[] valeurs,
			Class[] classes) {

		ArrayList<Class> list = trieClasses(classes);

		Class found = null;
		for (Class c : list) {
			System.out.println("show fields of " + c.getName());

			Field[] fields = getAllField(c);
			for (Field f : fields) {
				System.out.println(f.getName());
			}

			if (sameFieldAndType(fields, noms, valeurs)) {
				found = c;
				break;
			}

		}

		System.out.println("class found = " + found.getName());

		Object res = null;
		try {
			res = found.newInstance();

		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}

		return res;
	}

}
